package com.glp.work.flow.workflow.plugin.flowable.service.impl;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.github.pagehelper.PageInfo;
import com.github.pagehelper.page.PageMethod;
import com.glp.common.enums.ReturnEnum;
import com.glp.common.reponse.BaseResponse;
import com.glp.common.reponse.BaseResult;
import com.glp.work.flow.constant.*;
import com.glp.work.flow.controller.WfProcessInitiateController;
import com.glp.work.flow.dto.*;
import com.glp.work.flow.dto.request.ModelDto;
import com.glp.work.flow.dto.request.ModelListRequestDto;
import com.glp.work.flow.dto.request.ProcTaskAssignInfoDTO;
import com.glp.work.flow.exception.APIException;
import com.glp.work.flow.mapper.*;
import com.glp.work.flow.pojo.ProcessRecord;
import com.glp.work.flow.pojo.WfPlatformDef;
import com.glp.work.flow.pojo.WfPlatformDefModle;
import com.glp.work.flow.pojo.WfTaskAssign;
import com.glp.work.flow.request.ProcessInitiateRequest;
import com.glp.work.flow.response.ProcessInitiateResponse;
import com.glp.work.flow.service.CodeService;
import com.glp.work.flow.service.UserService;
import com.glp.work.flow.service.UserTaskAssignService;
import com.glp.work.flow.service.WfPlatformDefService;
import com.glp.work.flow.utils.BpmnModelUtils;
import com.glp.work.flow.utils.DateUtils;
import com.glp.work.flow.utils.IDUtils;
import com.glp.work.flow.workflow.plugin.flowable.constant.FlowConstant;
import com.glp.work.flow.workflow.plugin.flowable.converter.CustomBpmnJsonConverter;
import com.glp.work.flow.workflow.plugin.flowable.dto.*;
import com.glp.work.flow.workflow.plugin.flowable.service.FlowProcessDefinitionService;
import com.glp.work.flow.workflow.plugin.flowable.service.FlowTaskService;
import com.glp.work.flow.workflow.plugin.flowable.util.DateUtil;
import com.glp.work.flow.workflow.plugin.flowable.util.FlowUtils;
import com.glp.work.flow.workflow.plugin.flowable.validate.CustomProcessValidatorFactory;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.flowable.bpmn.BpmnAutoLayout;
import org.flowable.bpmn.converter.BpmnXMLConverter;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.*;
import org.flowable.common.engine.api.FlowableException;
import org.flowable.editor.constants.ModelDataJsonConstants;
import org.flowable.editor.language.json.converter.BpmnJsonConverter;
import org.flowable.engine.FormService;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.form.FormProperty;
import org.flowable.engine.form.StartFormData;
import org.flowable.engine.impl.persistence.entity.ProcessDefinitionEntityImpl;
import org.flowable.engine.repository.*;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.image.impl.DefaultProcessDiagramGenerator;
import org.flowable.ui.common.util.XmlUtil;
import org.flowable.validation.ProcessValidator;
import org.flowable.validation.ValidationError;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import java.util.stream.Stream;


/**
 * @author Pan Wang
 * @date: 2019/4/10
 */
@Service
@Slf4j
public class FlowProcessDefinitionServiceImpl implements FlowProcessDefinitionService {

    @Autowired
    FlowTaskService flowTaskService;

    @Autowired
    RepositoryService repositoryService;

    @Autowired
    RuntimeService runtimeService;

    @Autowired
    FormService formService;

    @Resource
    UserService userService;

    @Resource
    CodeService codeService;

    @Resource
    WfOrderMapper wfOrderMapper;

    @Autowired
    UserTaskAssignService userTaskAssignService;

    @Autowired
    private WfPlatformDefMapper wfPlatformDefMapper;

    @Autowired
    private WfPlatformDefService wfPlatformDefService;

    @Autowired
    private ProcessRecordMapper processRecordMapper;

    @Autowired
    private FlowProcessDefinitionServiceImpl flowProcessDefinitionService;

    @Resource
    private WfProcessInitiateController wfProcessInitiateController;

    @Value("${work.flow.deploy.instance.valid:true}")
    private Boolean deployInstanceValid;
    @Value("${glp.fbs-app.appId}")
    private String appId;
    @Value("${glp.process.detail}")
    private String processDetail;
    @Autowired
    private WfTaskAssignMapper wfTaskAssignMapper;
    @Autowired
    WfPlatformDefModleMapper wfPlatformDefModleMapper;
    CustomBpmnJsonConverter bpmnJsonConverter = new CustomBpmnJsonConverter();


    @Override
    public String uploadBPMN(MultipartFile file, String userNo) {
        BaseResult<UserDTO> b = userService.getPersonInfo(userNo);
        UserDTO user = b.getData();
        if (user == null) {
            throw new APIException(APICode.DATA_ERROR, "导入异常！当前用户信息不存在！");
        }

        if (file == null) {
            throw new APIException(APICode.ERROR, "请选择上传的文件");
        }
        if (StringUtils.isEmpty(file.getOriginalFilename()) || !(file.getOriginalFilename().endsWith(".bpmn") || file.getOriginalFilename().endsWith(".bpmn20.xml"))) {
            throw new APIException(APICode.ERROR, "文件格式错误");
        }
        try {
            XMLInputFactory xif = XmlUtil.createSafeXmlInputFactory();
            InputStreamReader xmlIn = new InputStreamReader(file.getInputStream(), StandardCharsets.UTF_8);
            XMLStreamReader xtr = xif.createXMLStreamReader(xmlIn);
            BpmnModel bpmnModel = new BpmnXMLConverter().convertToBpmnModel(xtr);
            if (CollectionUtils.isEmpty(bpmnModel.getProcesses())) {
                throw new APIException(APICode.ERROR, "找不到定义的流程");
            }
            if (bpmnModel.getLocationMap().size() == 0) {
                BpmnAutoLayout bpmnLayout = new BpmnAutoLayout(bpmnModel);
                bpmnLayout.execute();
            }
            ObjectNode modelNode = bpmnJsonConverter.convertToJson(bpmnModel);

            Process process = bpmnModel.getMainProcess();
            String key = process.getId();
            String name = process.getName();
            String description = process.getDocumentation();

            List<Model> models = repositoryService.createModelQuery().modelKey(key).orderByModelId().desc().list();
            Integer verstion = 1;
            if (null != models && models.size() > 0) {
                throw new APIException(APICode.ERROR, "该流程已存在!");
//                key = key+"_"+System.currentTimeMillis();
//                ObjectNode propertiesNode = (ObjectNode) modelNode.get("properties");
//                propertiesNode.put(StencilConstants.PROPERTY_PROCESS_ID, key);
                //verstion = (models.get(0)==null||models.get(0).getVersion()==null?1:models.get(0).getVersion()+1);
            }

            Model model = FlowUtils.buildModel(repositoryService.newModel(), FlowConstant.DEFAULT_CATEGORY, name, key, description, verstion);
            repositoryService.saveModel(model);
            repositoryService.addModelEditorSource(model.getId(), modelNode.toString().getBytes(StandardCharsets.UTF_8));
            Example example = new Example(ProcessRecord.class);
            example.createCriteria().andEqualTo("modelId", model.getId());
            ProcessRecord record = processRecordMapper.selectOneByExample(example);
            if (record == null) {
                record = new ProcessRecord();
                record.setCreateUserId(userNo);
                record.setCreateUserName(user.getName());
                record.setUpdateUserId(userNo);
                record.setCreateTime(DateUtils.getCurrent());
                record.setUpdateUserName(user.getName());
                record.setUpdateTime(DateUtils.getCurrent());
                //record.setProcessId(procDefId);
                record.setModelId(model.getId());
                processRecordMapper.insert(record);
            }
            return model.getId();
        } catch (Exception e) {
            log.error("导入失败 {0}", e.getMessage(), e);
            throw new APIException(APICode.ERROR, e.getMessage());
        }
    }

    @Override
    public BaseResult addModel(ModelCreateDto dto) {
        dto.setKey(codeService.generateWithDigits(CodeFactorEnum.LC.name(), 6));
        List<Model> models = repositoryService.createModelQuery().modelKey(dto.getKey()).orderByModelId().desc().list();
        Integer verstion = 1;
        if (null != models && models.size() > 0) {
            verstion = (models.get(0) == null || models.get(0).getVersion() == null ? 1 : models.get(0).getVersion() + 1);
        }
        Model model = FlowUtils.buildModel(repositoryService.newModel(), dto.getCategoryId(), dto.getName(), dto.getKey(), dto.getDescription(), 1);
        boolean hasOldKey = repositoryService.createModelQuery().modelKey(dto.getKey()).count() > 0;
        if (hasOldKey) {
            return BaseResponse.error("Key 已经存在！请修改！");
        }
        repositoryService.saveModel(model);
        Map<String, Object> editorNode = Maps.newLinkedHashMap();
        editorNode.put("resourceId", model.getId());
        Map<String, Object> properties = Maps.newLinkedHashMap();
        properties.put("process_id", dto.getKey());
//        properties.put("process_namespace", "https://github.com/threefish");
        properties.put("name", dto.getName());
        properties.put("documentation", dto.getDescription());
        editorNode.put("properties", properties);
        Map<String, Object> stencilSetNode = Maps.newLinkedHashMap();
        stencilSetNode.put("namespace", "http://b3mn.org/stencilset/bpmn2.0#");
        editorNode.put("stencilset", stencilSetNode);
        repositoryService.addModelEditorSource(model.getId(), new Gson().toJson(editorNode).getBytes(StandardCharsets.UTF_8));
        return BaseResponse.success(model.getId());
    }

    @Override
    public BaseResult addModelNew(String userNo, ModelCreateDto dto) {
        dto.setKey(codeService.generateWithDigits(CodeFactorEnum.LC.name(), 6));
        List<Model> models = repositoryService.createModelQuery().modelKey(dto.getKey()).orderByModelId().desc().list();
        Integer verstion = 1;
        if (null != models && models.size() > 0) {
            verstion = (models.get(0) == null || models.get(0).getVersion() == null ? 1 : models.get(0).getVersion() + 1);
        }
        Model model = FlowUtils.buildModel(repositoryService.newModel(), dto.getCategoryId(), dto.getName(), dto.getKey(), dto.getDescription(), 1);
        boolean hasOldKey = repositoryService.createModelQuery().modelKey(dto.getKey()).count() > 0;
        if (hasOldKey) {
            return BaseResponse.error("Key 已经存在！请修改！");
        }
        repositoryService.saveModel(model);
        Map<String, Object> editorNode = Maps.newLinkedHashMap();
        editorNode.put("resourceId", model.getId());
        Map<String, Object> properties = Maps.newLinkedHashMap();
        properties.put("process_id", dto.getKey());
//        properties.put("process_namespace", "https://github.com/threefish");
        properties.put("name", dto.getName());
        properties.put("documentation", dto.getDescription());
        editorNode.put("properties", properties);
        Map<String, Object> stencilSetNode = Maps.newLinkedHashMap();
        stencilSetNode.put("namespace", "http://b3mn.org/stencilset/bpmn2.0#");
        editorNode.put("stencilset", stencilSetNode);
        repositoryService.addModelEditorSource(model.getId(), new Gson().toJson(editorNode).getBytes(StandardCharsets.UTF_8));
        BaseResult<UserDTO> b = userService.getPersonInfo(userNo);
        UserDTO user = b.getData();
        if (user == null) {
            throw new APIException(APICode.DATA_ERROR, "新增模型异常！当前用户信息不存在！");
        }
        //保存创建人修改人信息
        ProcessRecord processRecord = new ProcessRecord();
        //processRecord.setProcessId(processDefinition.getId());
        processRecord.setModelId(model.getId());
        processRecord.setCreateUserId(userNo);
        processRecord.setCreateUserName(user.getName());
        processRecord.setCreateTime(DateUtils.getCurrent());
        processRecord.setUpdateUserId(userNo);
        processRecord.setUpdateUserName(user.getName());
        processRecord.setUpdateTime(DateUtils.getCurrent());
        processRecordMapper.insert(processRecord);
        return BaseResponse.success(model.getId());
    }

    @Override
    public BaseResult<ModelEntityVo> getModels(ModelListRequestDto dto) {
        ModelQuery modelQuery = repositoryService.createModelQuery().modelCategory(dto.getCategoryId()).latestVersion();
        List<Model> list = modelQuery.orderByCreateTime().desc().listPage(dto.getPageSize() * (dto.getPageNum() - 1), dto.getPageSize());
        long total = modelQuery.count();
        List<ModelEntityVo> entityVos = list.stream().map(m -> {
            ModelEntityVo vo = new ModelEntityVo();
            if (Strings.isNotBlank(m.getMetaInfo())) {
                vo.setDescription(m.getMetaInfo());
            }
            BeanUtils.copyProperties(m, vo);
            return vo;
        }).collect(Collectors.toList());
        PageInfo<ModelEntityVo> pages = PageInfo.of(entityVos);
        pages.setPageNum(dto.getPageNum());
        pages.setPageSize(dto.getPageSize());
        pages.setTotal(total);
        return BaseResponse.success(pages);
    }

    @Override
    public BaseResult<Map<String, Object>> modelInfo(String modelId) {
        Map<String, Object> modelNode = Maps.newHashMap();
        Model model = repositoryService.getModel(modelId);
        if (model != null) {
            try {
                modelNode.put(ModelDataJsonConstants.MODEL_NAME, model.getName());
                modelNode.put(ModelDataJsonConstants.MODEL_ID, model.getId());
                modelNode.put("revision", model.getVersion());
                modelNode.put("description", model.getMetaInfo());
                modelNode.put("key", model.getKey());
                modelNode.put("category", model.getCategory());
                byte[] bytes = repositoryService.getModelEditorSource(model.getId());
                modelNode.put("model", new Gson().fromJson(new String(bytes), LinkedHashMap.class));
            } catch (Exception e) {
                log.error("创建JSON模型时出错", e);
                throw new FlowableException("创建JSON模型时出错", e);
            }
        }
        return new BaseResult<>(ReturnEnum.SUCCESS.getCode(), ReturnEnum.SUCCESS.getMessage(), modelNode);
    }

    @Override
    public BaseResult modelStatusUpdatedeploy(String cachedValue) {
        /**
         * split[0]:流程id
         * split[1]:状态
         * split[2]:模板id
         * split[3]:userNo
         * split[4]:userName
         */
        String[] split = cachedValue.split(",");
        if (ProcessStatusEnum.ACTIVE.getCode().equals(split[1])) {
            return modelStatusUpdateNew(split[0], ProcessStatusEnum.ACTIVE.getCode(), split[2], split[3], split[4]);//启用
        } else if (ProcessStatusEnum.SUSPEND.getCode().equals(split[1])) {
            return modelStatusUpdateNew(split[0], ProcessStatusEnum.SUSPEND.getCode(), split[2], split[3], split[4]);//禁用
        } else if (ProcessStatusEnum.ARCHIVE.getCode().equals(split[1])) {
            return modelStatusUpdateNew(split[0], ProcessStatusEnum.ARCHIVE.getCode(), split[2], split[3], split[4]);//归档
        } else if (ProcessStatusEnum.RECOVER.getCode().equals(split[1])) {
            return modelStatusUpdateNew(split[0], ProcessStatusEnum.RECOVER.getCode(), split[2], split[3], split[4]);//恢复
        }
        return BaseResponse.error("操作失败!");
    }

    @Override
    public BaseResult modelStatusUpdate(String procDefId, String status) {
        try {
            if (ProcessStatusEnum.ACTIVE.getCode().equals(status)) {
                repositoryService.activateProcessDefinitionById(procDefId, true, null);
                return BaseResponse.success(ReturnEnum.SUCCESS.getCode(), "已激活ID为[" + procDefId + "]的流程定义。");
            } else if (ProcessStatusEnum.SUSPEND.getCode().equals(status)) {
                repositoryService.suspendProcessDefinitionById(procDefId, true, null);
                return BaseResponse.success(ReturnEnum.SUCCESS.getCode(), "已挂起ID为[" + procDefId + "]的流程定义。");
            }
        } catch (Exception e) {
            log.info("更新状态失败", e);
        }
        return BaseResponse.error("更新状态失败");
    }

    @Override
    public BaseResult modelStatusUpdateNew(String procDefId, String status, String modelId, String userNo, String userName) {
        try {
            Example example = new Example(ProcessRecord.class);
            example.createCriteria().andEqualTo("modelId", modelId);
            ProcessRecord record = processRecordMapper.selectOneByExample(example);
            if (record == null) {
                record = new ProcessRecord();
                record.setCreateUserId(userNo);
                record.setCreateUserName(userName);
                record.setUpdateUserId(userNo);
                record.setCreateTime(DateUtils.getCurrent());
                record.setUpdateUserName(userName);
                record.setUpdateTime(DateUtils.getCurrent());
                record.setProcessId(procDefId);
                record.setModelId(modelId);
                processRecordMapper.insert(record);
            }
            String operation = "";
            if (ProcessStatusEnum.ACTIVE.getCode().equals(status)) {
                repositoryService.activateProcessDefinitionById(procDefId, true, null);
                operation = ProcessStatusEnum.ACTIVE.getRemark();
                record.setOperation(ProcessStatusEnum.ACTIVE.getCode());
            } else if (ProcessStatusEnum.SUSPEND.getCode().equals(status)) {
                try {
                    List<ProcessDefinition> processDefinitions = repositoryService.createProcessDefinitionQuery()
                            .processDefinitionId(procDefId).list();
                    Optional<ProcessDefinition> max = processDefinitions.stream().max(Comparator.comparing(ProcessDefinition::getVersion));
                    if (max.isPresent()) {
                        if (!max.get().isSuspended()) {
                            repositoryService.suspendProcessDefinitionById(procDefId, true, null);
                        }
                    }
                } catch (Exception e) {
                    log.error("挂起流程异常", e);
                    e.printStackTrace();
                }
                operation = ProcessStatusEnum.SUSPEND.getRemark();
                record.setOperation(ProcessStatusEnum.SUSPEND.getCode());
            } else if (ProcessStatusEnum.ARCHIVE.getCode().equals(status)) {
                record.setOperation(ProcessStatusEnum.ARCHIVE.getCode());
                operation = ProcessStatusEnum.ARCHIVE.getRemark();
                try {
                    repositoryService.suspendProcessDefinitionById(procDefId, true, null);
                } catch (Exception e) {
                    log.error("挂起流程异常", e);
                    e.printStackTrace();
                }
            } else if (ProcessStatusEnum.RECOVER.getCode().equals(status)) {
                record.setOperation(ProcessStatusEnum.RECOVER.getCode());
                operation = ProcessStatusEnum.RECOVER.getRemark();
            } else if (ProcessStatusEnum.APPROVAL.getCode().equals(status)) {
                record.setOperation(ProcessStatusEnum.APPROVAL.getCode());
                operation = ProcessStatusEnum.APPROVAL.getRemark();
            } else {
                record.setOperation(ProcessStatusEnum.NO.getCode());
            }
            record.setUpdateUserId(userNo);
            record.setUpdateUserName(userName);
            record.setUpdateTime(DateUtils.getCurrent());
            processRecordMapper.updateByExampleSelective(record, example);
            return BaseResponse.success(ReturnEnum.SUCCESS.getCode(), "已" + operation + "ID为[" + procDefId + "]的流程定义。");
        } catch (Exception e) {
            log.info("更新状态失败", e);
        }
        return BaseResponse.error("更新状态失败");
    }

    @Override
    public List<ValidationError> validate(String json) {
        List<ValidationError> errors = new ArrayList<>();
        try {
            ObjectNode modelNode = (ObjectNode) new ObjectMapper().readTree(new StringReader(json));
            BpmnModel bpmnModel = bpmnJsonConverter.convertToBpmnModel(modelNode);
            ProcessValidator validator = new CustomProcessValidatorFactory().createDefaultProcessValidator();
            errors = validator.validate(bpmnModel);
        } catch (IOException e) {
            log.error("模板定义校验失败", e);
        }
        return errors;
    }

    @Override
    public BaseResult<String> saveModel(String modelId, ModelSaveDto dto) {
        try {
            Model model = repositoryService.getModel(modelId);
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode jsonNode = objectMapper.readTree(dto.getJson_xml());
            BpmnJsonConverter jsonConverter = new BpmnJsonConverter();
            BpmnModel bpmnModel = jsonConverter.convertToBpmnModel(jsonNode);
            //动态增加监听器
            BpmnModelUtils.defaultDynamicAddEventListener(bpmnModel);
            String bpmnJson = jsonConverter.convertToJson(bpmnModel).toString();
            log.info("流程定义JSON：{}", bpmnJson);
            {//校验流程定义是否正确
                ProcessValidator validator = new CustomProcessValidatorFactory().createDefaultProcessValidator();
                List<ValidationError> errors = validator.validate(bpmnModel);
                if (CollectionUtils.isNotEmpty(errors)) {
                    ValidationError error = errors.get(0);
                    return new BaseResult<>(ReturnEnum.ERROR.getCode(), error.getActivityName() + " : [" + error.getDefaultDescription() + "]");
                }
            }

            model.setKey(dto.getKey());
            model.setName(dto.getName());
            if (StringUtils.isNotBlank(model.getDeploymentId())) {
                model.setVersion(model.getVersion() + 1);
            }
            model.setMetaInfo(dto.getDescription());
            model.setDeploymentId(null);
            model.setCategory(FlowConstant.DEFAULT_CATEGORY);
            repositoryService.saveModel(model);
            repositoryService.addModelEditorSource(model.getId(), bpmnJson.getBytes(StandardCharsets.UTF_8));
            return new BaseResult<>(APICode.SUCCESS.getCode(), "保存成功！");
        } catch (Exception e) {
            log.error("模型保存失败", e);
            return new BaseResult<>(ReturnEnum.ERROR.getCode(), "模型保存失败" + e.getLocalizedMessage());
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public BaseResult<String> saveModel2(String modelId, ModelSaveDto dto, String userNo) {
        try {
            BaseResult<UserDTO> b = userService.getPersonInfo(userNo);
            UserDTO user = b.getData();
            if (user == null) {
                throw new APIException(APICode.DATA_ERROR, "保存模型异常！当前用户信息不存在！");
            }
            Model model = repositoryService.getModel(modelId);
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode jsonNode = objectMapper.readTree(dto.getJson_xml());
            BpmnJsonConverter jsonConverter = new BpmnJsonConverter();
            BpmnModel bpmnModel = jsonConverter.convertToBpmnModel(jsonNode);
            //动态增加监听器
            BpmnModelUtils.defaultDynamicAddEventListener(bpmnModel);
            String bpmnJson = jsonConverter.convertToJson(bpmnModel).toString();
            log.info("流程定义JSON：{}", bpmnJson);
            {//校验流程定义是否正确
                ProcessValidator validator = new CustomProcessValidatorFactory().createDefaultProcessValidator();
                List<ValidationError> errors = validator.validate(bpmnModel);
                if (CollectionUtils.isNotEmpty(errors)) {
                    ValidationError error = errors.get(0);
                    return new BaseResult<>(ReturnEnum.ERROR.getCode(), error.getActivityName() + " : [" + error.getDefaultDescription() + "]");
                }
            }

            model.setKey(dto.getKey());
            model.setName(dto.getName());
            if (StringUtils.isNotBlank(model.getDeploymentId())) {
                model.setVersion(model.getVersion() + 1);
            }
            model.setMetaInfo(dto.getDescription());
            model.setDeploymentId(null);
            model.setCategory(FlowConstant.DEFAULT_CATEGORY);
            repositoryService.saveModel(model);
            repositoryService.addModelEditorSource(model.getId(), bpmnJson.getBytes(StandardCharsets.UTF_8));
            //编译成功自动部署
            String procDefId = flowProcessDefinitionService.deploy(model.getId());
            Model model1 = repositoryService.getModel(modelId);
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                    .deploymentId(model1.getDeploymentId())
                    .singleResult();
            //保存创建人修改人信息
            ProcessRecord processRecord = new ProcessRecord();
            processRecord.setProcessId(processDefinition.getId());
            processRecord.setModelId(model.getId());
            processRecord.setCreateTime(DateUtils.getCurrent());
            processRecord.setUpdateUserId(userNo);
            processRecord.setUpdateUserName(user.getName());
            processRecord.setUpdateTime(DateUtils.getCurrent());
            Example example = new Example(ProcessRecord.class);
            example.createCriteria().andEqualTo("modelId", model.getId());
            ProcessRecord record = processRecordMapper.selectOneByExample(example);
            if (record == null) {
                processRecord.setCreateUserId(userNo);
                processRecord.setCreateUserName(user.getName());
                processRecordMapper.insert(processRecord);
            } else {
                processRecordMapper.updateByExampleSelective(processRecord, example);
            }
            modelStatusUpdateNew(processDefinition.getId(), "suspend", model.getId(), userNo, user.getName());

            //*******保存用户节点到   wf_task_assign
            for (FlowElement flowElement : bpmnModel.getMainProcess().getFlowElements()) {
                if (flowElement instanceof UserTask) {
                    UserTask userTask = (UserTask) flowElement;
                    WfTaskAssign wfTaskAssign = new WfTaskAssign();
                    wfTaskAssign.setTaskDefId(userTask.getId());
                    wfTaskAssign.setTaskDefKey(userTask.getName());
                    wfTaskAssign.setTaskDefRule(TaskingType.NONE.getCode());
                    wfTaskAssign.setTaskDefBatch(Constants.STATUS_1);
                    wfTaskAssign.setProcDefId(procDefId);
                    wfTaskAssign.setProcDefKey(model.getKey());
                    wfTaskAssign.setCreateUser(user.getName());
                    wfTaskAssign.setUpdateUser(user.getName());
                    wfTaskAssign.setCreateTime(DateUtils.getCurrent());
                    wfTaskAssign.setUpdateTime(DateUtils.getCurrent());
                    wfTaskAssignMapper.insertSelective(wfTaskAssign);
                }
            }
            return new BaseResult<>(APICode.SUCCESS.getCode(), "保存成功！");
        } catch (Exception e) {
            log.error("模型保存失败", e);
            return new BaseResult<>(ReturnEnum.ERROR.getCode(), "模型保存失败" + e.getLocalizedMessage());
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public BaseResult<String> saveModelNew(ModelDto modelDto, String userNo) {

        try {
            BaseResult<UserDTO> b = userService.getPersonInfo(userNo);
            UserDTO user = b.getData();
            if (user == null) {
                throw new APIException(APICode.DATA_ERROR, "保存模型异常！当前用户信息不存在！");
            }
            Model model = repositoryService.getModel(modelDto.getModelId());
            for (ProcTaskAssignInfoDTO procTaskAssignInfoDTO : modelDto.getProcTaskAssignInfoDTOs()) {
                if (StringUtils.isEmpty(procTaskAssignInfoDTO.getTaskDefKey())) {
                    throw new APIException(APICode.ERROR, ",必须在设计中填写用户节点名称!");
                }
            }
            model.setMetaInfo(modelDto.getDescription());
            verificationDisable(modelDto, model);
            Model model1 = repositoryService.getModel(modelDto.getModelId());
            //流程
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                    .deploymentId(model1.getDeploymentId())
                    .singleResult();
            //保存创建人修改人信息
            ProcessRecord processRecord = new ProcessRecord();
            Example example = new Example(ProcessRecord.class);
            example.createCriteria().andEqualTo("modelId", model.getId());
            ProcessRecord record = processRecordMapper.selectOneByExample(example);
            processRecord.setProcessId(processDefinition.getId());
            processRecord.setCreateTime(DateUtils.getCurrent());
            processRecord.setUpdateUserId(userNo);
            processRecord.setUpdateUserName(user.getName());
            processRecord.setUpdateTime(DateUtils.getCurrent());
            processRecord.setModelId(modelDto.getModelId());
            if (record == null) {
                processRecord.setCreateUserId(userNo);
                processRecord.setCreateUserName(user.getName());
                processRecordMapper.insert(processRecord);
            } else {
                processRecordMapper.updateByExampleSelective(processRecord, example);
            }

            for (ProcTaskAssignInfoDTO procTaskAssignInfoDTO : modelDto.getProcTaskAssignInfoDTOs()) {
                procTaskAssignInfoDTO.setProcDefId(processRecord.getProcessId());
                log.info("保存任务分配的信息：{}", procTaskAssignInfoDTO);
                userTaskAssignService.saveTaskAssignInfoNew(procTaskAssignInfoDTO);
            }

            log.info("应用授权");
            wfPlatformDefService.authorization(modelDto.getPlatformIds(), modelDto.getMqKey(), modelDto.getMessageType(), model.getKey(), userNo);
            modelStatusUpdateNew(processDefinition.getId(), "suspend", model.getId(), userNo, user.getName());
            return new BaseResult<>(APICode.SUCCESS.getCode(), "保存成功！");
        } catch (Exception e) {
            log.error("模型保存失败", e);
            return new BaseResult<>(ReturnEnum.ERROR.getCode(), "模型保存失败" + e.getLocalizedMessage());
        }
    }

    /***
     * @description : 判断各个节点配置信息是否相同，如果相同就不禁用
     * @params : [procTaskAssignInfoDTOs, procDefId]
     * @returns : boolean
     * @author : 郭永伟
     * @date : 2020/12/18
     */
    void verificationDisable(ModelDto modelDto, Model model) {
        log.info("比对修改的是否是表单内容：{}", modelDto.getProcTaskAssignInfoDTOs());
        BpmnModel bpmnModel = repositoryService.getBpmnModel(modelDto.getProcDefId());
        BpmnModelUtils.defaultDynamicAddEventListener(bpmnModel);
        boolean f = false;
        for (FlowElement flowElement : bpmnModel.getMainProcess().getFlowElements()) {
            if (flowElement instanceof UserTask) {
                UserTask userTask = (UserTask) flowElement;
                for (ProcTaskAssignInfoDTO proc : modelDto.getProcTaskAssignInfoDTOs()) {
                    if (proc.getTaskDefId().equals(userTask.getId())) {
                        if (proc.getTaskDefForm() != null) {
                            if (!proc.getTaskDefForm().equals(userTask.getFormKey())) {
                                userTask.setFormKey(proc.getTaskDefForm());
                                f = true;
                            }
                        } else if (userTask.getFormKey() != null && proc.getTaskDefForm() == null) {
                            userTask.setFormKey(null);
                            f = true;
                        }
                    }
                }
            }
        }
        if (f) {
            BpmnJsonConverter jsonConverter = new BpmnJsonConverter();
            String bpmnJson = jsonConverter.convertToJson(bpmnModel).toString();
            if (StringUtils.isNotBlank(model.getDeploymentId())) {
                model.setVersion(model.getVersion() + 1);
            }
            repositoryService.saveModel(model);
            repositoryService.addModelEditorSource(model.getId(), bpmnJson.getBytes(StandardCharsets.UTF_8));
            flowProcessDefinitionService.deploy(model.getId());
        }

    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public String deploy(String modelId) {
        Model modelData = repositoryService.getModel(modelId);
        if (modelData == null) {
            throw new APIException(APICode.ERROR, "找不到流程定义文件。modelId=" + modelId);
        }
        String srcJson = new String(repositoryService.getModelEditorSource(modelData.getId()), StandardCharsets.UTF_8);
        log.info("流程部署，SOURCE：{}", srcJson);
        BpmnModel model;
        try {
            model = new BpmnJsonConverter().convertToBpmnModel((ObjectNode) new ObjectMapper().readTree(srcJson));
        } catch (IOException e) {
            log.error("流程部署失败！", e);
            throw new APIException(APICode.DATA_ERROR, "流程部署失败！");
        }
        if (model == null || model.getMainProcess() == null) {
            throw new APIException(APICode.DATA_ERROR, "流程定义的主流程不能为空！");
        }
        byte[] bpmnBytes = new BpmnXMLConverter().convertToXML(model, "UTF-8");
        String processName = modelData.getName() + ".bpmn20.xml";
        Deployment deployment = repositoryService.createDeployment().name(modelData.getName()).category(FlowConstant.DEFAULT_CATEGORY).addString(processName, new String(bpmnBytes)).deploy();
        modelData.setDeploymentId(deployment.getId());
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .deploymentId(deployment.getId())
                .singleResult();
        repositoryService.saveModel(modelData);
        log.info("部署成功，流程定义key=" + processDefinition.getKey());
        return processDefinition.getId();
    }


    @Override
    public List<UserTaskDto> userTaskDetailsNew(String modelId) {
        List<UserTaskDto> list = Lists.newArrayList();
        Model model = repositoryService.getModel(modelId);
        String deploymentId = model.getDeploymentId();
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .deploymentId(deploymentId)
                .singleResult();
        String id = processDefinition.getId();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(id);
        Process process = bpmnModel.getProcesses().get(0);
        Collection<FlowElement> flowElements = process.getFlowElements();
        if (CollectionUtils.isNotEmpty(flowElements)) {
            for (FlowElement flowElement : flowElements) {
                if (flowElement instanceof UserTask) {
                    UserTask task = (UserTask) flowElement;
                    UserTaskDto userTaskDto = new UserTaskDto();
                    userTaskDto.setTaskName(task.getName());
                    String assignee = task.getAssignee();
                    if (!StringUtils.isEmpty(assignee)) {
                        BaseResult personInfo = userService.getPersonInfo(assignee);
                        if (personInfo != null && personInfo.getData() != null) {
                            if (personInfo.getData() instanceof UserDTO) {
                                String name = ((UserDTO) personInfo.getData()).getName();
                                userTaskDto.setUserName(name);
                            }
                        }
                    }
                    userTaskDto.setCreateTime(model.getCreateTime());
                    userTaskDto.setUpdateTime(model.getLastUpdateTime());
                    list.add(userTaskDto);
                }
            }
        }
        return list;
    }


    @Override
    public void delete(String modelId) {
        Model modelData = repositoryService.getModel(modelId);
        if (Strings.isNotBlank(modelData.getDeploymentId())) {
            repositoryService.deleteDeployment(modelData.getDeploymentId(), true);
        }
        repositoryService.deleteModel(modelId);
    }


    /**
     * 获取流程定义
     *
     * @param procDefKey 流程定义KEY
     * @return
     */
    @Override
    public Map<String, Object> getProcessDefinitionByKey(String procDefKey) {
        Map<String, Object> pdMap = Maps.newHashMapWithExpectedSize(2);
        StartFormData startFormData = formService.getStartFormData(procDefKey);
        List<FormProperty> formProperties = startFormData.getFormProperties();
        ProcessDefinition pd = startFormData.getProcessDefinition();
        pdMap.put("formData", formProperties);
        pdMap.put("processDefinition", pd);
        return pdMap;
    }

    /**
     * 流程定义列表
     */
    @Override
    public FlowDataListDTO<ProcessDefinitionEntitDTO> queryProcessDefinitionList(FlowDataListDTO<ProcessDefinitionEntitDTO> vo) {
        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery().latestVersion().orderByProcessDefinitionKey().asc();
//        processDefinitionQuery.processDefinitionCategory(FlowConstant.DEFAULT_CATEGORY);
        vo.setCount((int) processDefinitionQuery.count());
        List<ProcessDefinition> processDefinitionList = processDefinitionQuery.listPage(vo.getFirstResult(), vo.getPageSize());
        for (ProcessDefinition processDefinition : processDefinitionList) {
            String deploymentId = processDefinition.getDeploymentId();
            Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult();
            ProcessDefinitionEntitDTO processDefinitionEntitDto = new ProcessDefinitionEntitDTO((ProcessDefinitionEntityImpl) processDefinition);
            processDefinitionEntitDto.setCategory(deployment.getCategory());
            processDefinitionEntitDto.setCategoryName(FlowConstant.DEFAULT_CATEGORY_NAME);
            processDefinitionEntitDto.setDeploymentTime(deployment.getDeploymentTime());
            vo.getData().add(processDefinitionEntitDto);
        }
        return vo;
    }

    @Override
    public PageInfo<ProcessDefinitionEntitDTO> queryProcessDefinitionList(ProcessDefQueryDto dto) {
        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery().latestVersion().orderByProcessDefinitionKey().asc();
        List<ProcessDefinition> processDefinitionList = processDefinitionQuery.list();
        Stream<ProcessDefinitionEntitDTO> dtoStream = processDefinitionList.stream().map(processDefinition -> {
            String deploymentId = processDefinition.getDeploymentId();
            Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult();
            ProcessDefinitionEntitDTO processDefinitionEntitDto = new ProcessDefinitionEntitDTO((ProcessDefinitionEntityImpl) processDefinition);
            if (deployment != null) {
                processDefinitionEntitDto.setCategory(deployment.getCategory());
                processDefinitionEntitDto.setDeploymentTime(deployment.getDeploymentTime());
            }
            processDefinitionEntitDto.setCategoryName(FlowConstant.DEFAULT_CATEGORY_NAME);
            return processDefinitionEntitDto;
        });
        dtoStream = dtoStream
                .filter(processDefinitionEntitDTO -> {
                    if (dto.getStartDate() == null) {
                        return true;
                    }
                    return (dto.getStartDate().getTime() -
                            processDefinitionEntitDTO.getDeploymentTime().getTime()) <= 0;

                }).filter(processDefinitionEntitDTO -> {
                    if (dto.getEndDate() == null) {
                        return true;
                    }
                    return (dto.getEndDate().getTime() - processDefinitionEntitDTO.getDeploymentTime().getTime()) >= 0;

                }).filter(processDefinitionEntitDTO -> {
                    if (dto.getSuspensionState() == null) {
                        return true;
                    }
                    return processDefinitionEntitDTO.getSuspensionState().equals(dto.getSuspensionState());
                }).filter(processDefinitionEntitDTO -> {
                    if (dto.getName() == null) {
                        return true;
                    }
                    return processDefinitionEntitDTO.getName().contains(dto.getName());
                });


        List<ProcessDefinitionEntitDTO> collect = dtoStream.collect(Collectors.toList());
        List<List<ProcessDefinitionEntitDTO>> partition = Lists.partition(collect, dto.getPageSize());
        List<ProcessDefinitionEntitDTO> processDefinitionEntitDTOS;
        if (partition.size() >= dto.getPageNum()) {
            processDefinitionEntitDTOS = partition.get(dto.getPageNum() - 1);
        } else {
            processDefinitionEntitDTOS = new ArrayList<>();
        }
        PageInfo<ProcessDefinitionEntitDTO> page = PageInfo.of(processDefinitionEntitDTOS);
        page.setTotal(collect.size());
        page.setPageNum(dto.getPageNum());
        page.setPageSize(dto.getPageSize());
        return page;
    }

    /**
     * 读取资源，通过部署ID
     *
     * @param processDefinitionId 流程定义ID
     * @param processInstanceId   流程实例ID
     * @param resourceType        资源类型(xml|image)
     */
    @Override
    public InputStream resourceRead(String processDefinitionId, String processInstanceId, String resourceType) {
        InputStream resourceAsStream = null;
        if (Objects.equals("image", resourceType)) {
            String fontName = "黑体";
            BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
            DefaultProcessDiagramGenerator diagramGenerator = new DefaultProcessDiagramGenerator();
            resourceAsStream = diagramGenerator.generateDiagram(bpmnModel, "jpg", fontName, fontName, fontName,
                    null, 1.0, true);
        } else if (Objects.equals("xml", resourceType)) {
            if (StringUtils.isBlank(processDefinitionId)) {
                ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
                processDefinitionId = processInstance.getProcessDefinitionId();
            }
            ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId);
            resourceAsStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), processDefinition.getResourceName());
        }
        return resourceAsStream;
    }

    /**
     * 挂起、激活流程实例
     */
    @Override
    public String updateState(String state, String procDefId) {
        if ("active".equals(state)) {
            repositoryService.activateProcessDefinitionById(procDefId, true, null);
            return "已激活ID为[" + procDefId + "]的流程定义。";
        } else if ("suspend".equals(state)) {
            repositoryService.suspendProcessDefinitionById(procDefId, true, null);
            return "已挂起ID为[" + procDefId + "]的流程定义。";
        }
        return "无操作";
    }

    /**
     * 删除部署的流程，级联删除流程实例
     *
     * @param deploymentId 流程部署ID
     */
    @Override
    public void deleteDeployment(String deploymentId) {
        repositoryService.deleteDeployment(deploymentId, true);
    }


    /**
     * 获取end节点
     *
     * @param processDefId
     * @return FlowElement
     */
    @Override
    public FlowElement findEndFlowElement(String processDefId) {
        Process process = repositoryService.getBpmnModel(processDefId).getMainProcess();
        Collection<FlowElement> list = process.getFlowElements();
        for (FlowElement f : list) {
            if (f instanceof EndEvent) {
                return f;
            }
        }
        return null;
    }


    /**
     * 获取MainProcess
     *
     * @param processDefId
     * @return FlowElement
     */
    @Override
    public Process findMainProcess(String processDefId) {
        return repositoryService.getBpmnModel(processDefId).getMainProcess();
    }

    /**
     * 获取外部表单执行器表达式
     *
     * @param processDefId
     * @return FlowElement
     */
    @Override
    public String findExternalFormExecutor(String processDefId) {
        Process process = findMainProcess(processDefId);
        AtomicReference<String> externalFormExecutor = new AtomicReference<>();
        process.getExtensionElements().forEach((key, elements) -> {
            if (CustomBpmnJsonConverter.EXTERNAL_FORM_EXECUTOR.equals(key)) {
                elements.stream().filter(extensionElement -> CustomBpmnJsonConverter.EXTERNAL_FORM_EXECUTOR.equals(extensionElement.getName())).forEach(extensionElement -> {
                    externalFormExecutor.set(extensionElement.getElementText());
                });
            }
        });
        return externalFormExecutor.get();
    }

    /**
     * 获取指定节点的节点信息
     *
     * @param activityId          当前步骤ID
     * @param processDefinitionId 流程定义ID
     * @return
     */
    @Override
    public FlowElement getFlowElementByActivityIdAndProcessDefinitionId(String activityId, String processDefinitionId) {
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
        List<Process> processes = bpmnModel.getProcesses();
        if (CollectionUtils.isNotEmpty(processes)) {
            for (Process process : processes) {
                FlowElement flowElement = process.getFlowElement(activityId);
                if (flowElement != null) {
                    return flowElement;
                }
            }
        }
        return null;
    }

    /**
     * 取得用户节点
     *
     * @param activityId
     * @param processDefinitionId
     * @return
     */
    @Override
    public UserTask getUserTask(String activityId, String processDefinitionId) {
        FlowElement flowElement = getFlowElementByActivityIdAndProcessDefinitionId(activityId, processDefinitionId);
        if (flowElement != null && flowElement instanceof UserTask) {
            return (UserTask) flowElement;
        }
        return null;
    }

    /**
     * 取得用户节点
     *
     * @param activityId
     * @param processDefinitionId
     * @return
     */
    @Override
    public UserTaskExtensionDTO getUserTaskExtension(String activityId, String processDefinitionId) {
        UserTask userTask = getUserTask(activityId, processDefinitionId);
        return FlowUtils.getUserTaskExtension(userTask);
    }

    /**
     * 根据流程定义Key 获取所有UserTask节点
     *
     * @param processDefKey processDefKey
     * @return List<UserTask>
     */
    @Override
    public List<UserTask> getUserTaskList(String processDefKey) {
        String processDefId = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey(processDefKey).latestVersion().singleResult().getId();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefId);
        Process process = bpmnModel.getMainProcess();
        return process.findFlowElementsOfType(UserTask.class);
    }

    @Override
    public List<UserTask> getUserTaskListById(String proDefId) {
        BpmnModel bpmnModel = repositoryService.getBpmnModel(proDefId);
        Process process = bpmnModel.getMainProcess();
        return process.findFlowElementsOfType(UserTask.class);
    }

    @Override
    public List<FlowElement> getProcessNodeListById(String proDefId) {
        BpmnModel bpmnModel = repositoryService.getBpmnModel(proDefId);
        Process process = bpmnModel.getMainProcess();
        Collection<FlowElement> flowElements = process.getFlowElements();
        return flowElements.stream().filter(flowElement -> flowElement instanceof UserTask).collect(Collectors.toList());
    }

    @Override
    public void setUserTask(String moudelId, String proDefId, String origActId, String name, String documentation) {
        Model model = repositoryService.getModel(moudelId);
        BpmnModel bpmnModel = repositoryService.getBpmnModel(proDefId);
        BpmnModelUtils.defaultDynamicAddEventListener(bpmnModel);
        //Process process = bpmnModel.getMainProcess();
        for (FlowElement flowElement : bpmnModel.getMainProcess().getFlowElements()) {
            if (flowElement.getId().equals(origActId)) {
                if (flowElement instanceof UserTask) {
                    UserTask userTask = (UserTask) flowElement;
                    userTask.setName(name);
                    userTask.setFormKey(documentation);
                    break;
                }
            }
        }
        BpmnJsonConverter jsonConverter = new BpmnJsonConverter();
        String bpmnJson = jsonConverter.convertToJson(bpmnModel).toString();
        repositoryService.saveModel(model);
        repositoryService.addModelEditorSource(model.getId(), bpmnJson.getBytes(StandardCharsets.UTF_8));
    }

    @Override
    public ByteArrayOutputStream downLoadBpmn(String modelId) throws Exception {
        String srcJson = new String(repositoryService.getModelEditorSource(modelId), StandardCharsets.UTF_8);
        log.info("工作流模板文件下载Source！{}", srcJson);
        JsonNode editorNode = new ObjectMapper().readTree(srcJson);
        BpmnJsonConverter jsonConverter = new BpmnJsonConverter();
        BpmnModel model = jsonConverter.convertToBpmnModel(editorNode);
        byte[] bpmnBytes = new BpmnXMLConverter().convertToXML(model, "UTF-8");
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        bos.write(bpmnBytes);
        log.info("工作流模板文件下载！{}", model.getMainProcess().getId() + ".bpmn20.xml");
        return bos;
    }

    @Override
    public BaseResult userTaskDetails(String modelId) {
        List<UserTaskDto> list = Lists.newArrayList();
        Model model = repositoryService.getModel(modelId);
        String deploymentId = model.getDeploymentId();
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .deploymentId(deploymentId)
                .singleResult();
        String id = processDefinition.getId();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(id);
        Process process = bpmnModel.getProcesses().get(0);
        Collection<FlowElement> flowElements = process.getFlowElements();
        if (CollectionUtils.isNotEmpty(flowElements)) {
            for (FlowElement flowElement : flowElements) {
                if (flowElement instanceof UserTask) {
                    UserTask task = (UserTask) flowElement;
                    UserTaskDto userTaskDto = new UserTaskDto();
                    userTaskDto.setTaskName(task.getName());
                    String assignee = task.getAssignee();
                    if (!StringUtils.isEmpty(assignee)) {
                        BaseResult personInfo = userService.getPersonInfo(assignee);
                        if (personInfo != null && personInfo.getData() != null) {
                            if (personInfo.getData() instanceof UserDTO) {
                                String name = ((UserDTO) personInfo.getData()).getName();
                                userTaskDto.setUserName(name);
                            }
                        }
                    }
                    userTaskDto.setCreateTime(model.getCreateTime());
                    userTaskDto.setUpdateTime(model.getLastUpdateTime());
                    list.add(userTaskDto);
                }
            }
        }
        UserTaskVoDto vo = new UserTaskVoDto();
        vo.setModelId(modelId);
        vo.setTasks(list);
        return BaseResponse.success(vo);
    }

    @Override
    public PageInfo<ProcessAndModelVo> queryProcessAndModel2(ProcessAndModelDto processAndModelDto, Integer pageSize, Integer pageNum) {
        List<ProcessAndModelVo> list = wfPlatformDefMapper.queryProcessAndModel2(processAndModelDto);
        for (ProcessAndModelVo o : list) {
            if (StringUtils.isNotEmpty(processAndModelDto.getPlatformId())) {
                Long avgTime = wfPlatformDefMapper.findKeyOrder(o.getKey(), processAndModelDto.getPlatformId());
                String distanceTime = "";
                if (avgTime != null) {
                    distanceTime = DateUtil.getDistanceTime(avgTime);
                }
                o.setAvgTime(distanceTime);
            }
            if (StringUtils.isNotEmpty(o.getOperation())) {
                if (ProcessStatusEnum.ARCHIVE.getCode().equals(o.getOperation())) {
                    o.setSuspensionState(3);
                } else if (ProcessStatusEnum.APPROVAL.getCode().equals(o.getOperation())) {
                    o.setSuspensionState(4);
                }
            }
        }

        Stream<ProcessAndModelVo> stream = list.stream();

        stream = stream
                .filter(processAndModelVo -> {
                    if (processAndModelDto.getPlatformId() == null) {
                        return true;
                    }
                    for (WfPlatformDef platformDef : processAndModelVo.getWfPlatformDefs()) {
                        if (platformDef.getPlatformId().equals(processAndModelDto.getPlatformId())) {
                            return true;
                        }
                    }
                    return false;
                }).filter(processAndModelVo -> {
                    if (processAndModelDto.getSuspensionState() == null) {
                        return true;
                    }
                    if (processAndModelDto.getSuspensionState().equals(processAndModelVo.getSuspensionState())) {
                        return true;
                    }
                    return false;
                });
        List<ProcessAndModelVo> collect;
        collect = stream.collect(Collectors.toList());
        List<List<ProcessAndModelVo>> partition = Lists.partition(collect, pageSize);
        List<ProcessAndModelVo> processDefinitionEntitDTOS;
        if (partition.size() >= pageNum) {
            processDefinitionEntitDTOS = partition.get(pageNum - 1);
        } else {
            processDefinitionEntitDTOS = new ArrayList<>();
        }
        PageInfo<ProcessAndModelVo> page = PageInfo.of(processDefinitionEntitDTOS);
        page.setTotal(collect.size());
        page.setPageNum(pageNum);
        page.setPageSize(pageSize);
        return page;
    }

    @Override
    public BaseResult noModelStatusUpdatedeploy(String cachedValue) {
        /*
          split[0]:流程id
          split[1]:状态
          split[2]:模板id
          split[3]:userNo
          split[4]:userName
         */
        String[] split = cachedValue.split(",");
        if (ProcessStatusEnum.ACTIVE.getCode().equals(split[1])) {
            return modelStatusUpdateNew(split[0], "no", split[2], split[3], split[4]);
        } else if (ProcessStatusEnum.SUSPEND.getCode().equals(split[1])) {
            return modelStatusUpdateNew(split[0], "no", split[2], split[3], split[4]);
        } else if (ProcessStatusEnum.ARCHIVE.getCode().equals(split[1])) {
            return modelStatusUpdateNew(split[0], "no", split[2], split[3], split[4]);
        } else if (ProcessStatusEnum.RECOVER.getCode().equals(split[1])) {
            return modelStatusUpdateNew(split[0], "archive", split[2], split[3], split[4]);
        }
        return BaseResponse.error("操作失败!");
    }

    @Override
    public BaseResult processInitate(Map<String, Object> preVariable, UserDTO user, String superProcess, String[] split, List<WfPlatformDefModle> wfPlatformDefModles) {
        List<String> appNames = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(wfPlatformDefModles)) {
            List<String> collect = wfPlatformDefModles.stream().map(WfPlatformDefModle::getAppId).collect(Collectors.toList());
            WfPlatformDef wfPlatformDef = new WfPlatformDef();
            collect.forEach(appId -> {
                        wfPlatformDef.setPlatformId(appId);
                        appNames.add(wfPlatformDefMapper.selectOne(wfPlatformDef).getPlatformName());
                    }
            );
        }
        ProcessInitiateRequest processInitiateRequest = new ProcessInitiateRequest();
        processInitiateRequest.setAppId(appId);
        processInitiateRequest.setOrderId(IDUtils.getWfId(UUID.randomUUID().toString()));
        processInitiateRequest.setOrderTitle("流程变更审批");
        processInitiateRequest.setUserId(user.getUserNo());
        processInitiateRequest.setProcDefKey("LC000656");
        processInitiateRequest.setRemarks((String) preVariable.get("remarks"));
        Map<String, Object> processVariable = new HashMap<>();
        processVariable.put(FlowConstant.MODEL_KEY, preVariable.get("modelKey"));
        processVariable.put("superProcess", superProcess);
        processInitiateRequest.setProcessVariable(processVariable);
        Map<String, Object> dynamicForm = (Map<String, Object>) preVariable.get("dynamicForm");
        String s = appNames.toString();
        dynamicForm.put("appNames", s.substring(1, s.length() - 1));
        dynamicForm.put("processDetail", processDetail + preVariable.get("modelKey") + "?readonly=1");
        processInitiateRequest.setDynamicForm(dynamicForm);
        BaseResult<ProcessInitiateResponse> processInitiateResponseBaseResult = wfProcessInitiateController.processInitate(processInitiateRequest);
        log.info("超级流程发起工作流响应结果：processInitiateResponseBaseResult={}", processInitiateResponseBaseResult);
        //状态修改为审批中
        flowProcessDefinitionService.modelStatusUpdateNew(split[0], "approval", split[2], user.getUserNo(), user.getName());
        return new BaseResult(200, "成功", processInitiateResponseBaseResult);
    }

    @Override
    public PageInfo<ProcessAndModelVo> queryAPPProcess(String appId, Integer pageSize, Integer pageNum) {
        return PageMethod.startPage(
                pageNum, pageSize).doSelectPageInfo(() -> wfPlatformDefMapper.queryAPPProcess(appId));
    }


}
